/**
 * This file is part of 1genia trampoline
 * Copyright (C) 2007 1genia (contact@1genia.com)
 *
 * This library is free software; you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as
 * published by the Free Software Foundation; version 3 of the License. 
 *
 * This library is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Library General Public License for more details. 
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; see the file COPYING.TXT.  If not,
 * write to the Free Software Foundation, Inc., 51 Franklin Street,
 * Fifth Floor, Boston, MA 02110-1301, USA. 
 **/
package com.genia.toolbox.web.io;

import java.io.IOException;
import java.io.InputStream;

import javax.servlet.ServletInputStream;

/**
 * This class wrapps a <code>InputStream</code> into a
 * <code>ServletInputStream</code>. It delegates all its operation to the
 * underlying <code>InputStream</code>.
 */
class DumbServletInputStream
    extends ServletInputStream
{

  /**
   * the <code>InputStream</code> to wrapp.
   */
  private final transient InputStream inputStream;



  /**
   * Constructor.
   * 
   * @param inputStream
   *          the <code>InputStream</code> to wrapp
   */
  public DumbServletInputStream(final InputStream inputStream)
  {
    this.inputStream = inputStream;
  }



  /**
   * Returns the number of bytes that can be read (or skipped over) from this
   * input stream without blocking by the next caller of a method for this input
   * stream. The next caller might be the same thread or another thread.
   * 
   * @return the number of bytes that can be read from this input stream without
   *         blocking.
   * @throws IOException
   *           if an I/O error occurs.
   */
  @Override
  public int available()
      throws IOException
  {
    return this.inputStream.available();
  }



  /**
   * Closes this input stream and releases any system resources associated with
   * the stream.
   * <p>
   * The <code>close</code> method of <code>InputStream</code> does nothing.
   * 
   * @throws IOException
   *           if an I/O error occurs.
   */
  @Override
  public void close()
      throws IOException
  {
    this.inputStream.close();
  }



  /**
   * Marks the current position inputStream this input stream. A subsequent call
   * to the <code>reset</code> method repositions this stream at the last
   * marked position so that subsequent reads re-read the same bytes.
   * 
   * @param readlimit
   *          the maximum limit of bytes that can be read before the mark
   *          position becomes invalid.
   */
  @Override
  public void mark(final int readlimit)
  {
    this.inputStream.mark(readlimit);
  }



  /**
   * Tests if this input stream supports the <code>mark</code> and
   * <code>reset</code> methods. Whether or not <code>mark</code> and
   * <code>reset</code> are supported is an invariant property of a particular
   * input stream instance. The <code>markSupported</code> method of
   * <code>InputStream</code> returns <code>false</code>.
   * 
   * @return <code>true</code> if this stream instance supports the mark and
   *         reset methods; <code>false</code> otherwise.
   */
  @Override
  public boolean markSupported()
  {
    return this.inputStream.markSupported();
  }



  /**
   * Reads the next byte of data from the input stream. The value byte is
   * returned as an <code>int</code> inputStream the range <code>0</code> to
   * <code>255</code>. If no byte is available because the end of the stream
   * has been reached, the value <code>-1</code> is returned. This method
   * blocks until input data is available, the end of the stream is detected, or
   * an exception is thrown.
   * 
   * @return the next byte of data, or <code>-1</code> if the end of the
   *         stream is reached.
   * @throws IOException
   *           if an I/O error occurs.
   */
  @Override
  public int read()
      throws IOException
  {
    return this.inputStream.read();
  }



  /**
   * Reads some number of bytes from the input stream and stores them into the
   * buffer array <code>b</code>. The number of bytes actually read is
   * returned as an integer. This method blocks until input data is available,
   * end of file is detected, or an exception is thrown.
   * 
   * @param buffer
   *          the buffer into which the data is read.
   * @return the total number of bytes read into the buffer, or <code>-1</code>
   *         is there is no more data because the end of the stream has been
   *         reached.
   * @throws IOException
   *           if an I/O error occurs.
   */
  @Override
  public int read(final byte[] buffer)
      throws IOException
  {
    return this.inputStream.read(buffer);
  }



  /**
   * Reads up to <code>len</code> bytes of data from the input stream into an
   * array of bytes. An attempt is made to read as many as <code>len</code>
   * bytes, but a smaller number may be read. The number of bytes actually read
   * is returned as an integer.
   * 
   * @param buffer
   *          the buffer into which the data is read.
   * @param off
   *          the start offset inputStream array <code>b</code> at which the
   *          data is written.
   * @param len
   *          the maximum number of bytes to read.
   * @return the total number of bytes read into the buffer, or <code>-1</code>
   *         if there is no more data because the end of the stream has been
   *         reached.
   * @throws IOException
   *           if an I/O error occurs.
   */
  @Override
  public int read(final byte[] buffer, final int off, final int len)
      throws IOException
  {
    return this.inputStream.read(buffer, off, len);
  }



  /**
   * Repositions this stream to the position at the time the <code>mark</code>
   * method was last called on this input stream.
   * 
   * @throws IOException
   *           if this stream has not been marked or if the mark has been
   *           invalidated.
   */
  @Override
  public void reset()
      throws IOException
  {
    this.inputStream.reset();
  }



  /**
   * Skips over and discards <code>n</code> bytes of data from this input
   * stream. The <code>skip</code> method may, for a variety of reasons, end
   * up skipping over some smaller number of bytes, possibly <code>0</code>.
   * This may result from any of a number of conditions; reaching end of file
   * before <code>n</code> bytes have been skipped is only one possibility.
   * The actual number of bytes skipped is returned. If <code>n</code> is
   * negative, no bytes are skipped.
   * 
   * @param nbBytes
   *          the number of bytes to be skipped.
   * @return the actual number of bytes skipped.
   * @throws IOException
   *           if an I/O error occurs.
   */
  @Override
  public long skip(final long nbBytes)
      throws IOException
  {
    return this.inputStream.skip(nbBytes);
  }



  /**
   * Returns a string representation of the object. In general, the
   * <code>toString</code> method returns a string that "textually represents"
   * this object. The result should be a concise but informative representation
   * that is easy for a person to read.
   * 
   * @return a string representation of the object.
   */
  @Override
  public String toString()
  {
    return this.inputStream.toString();
  }
}
